package cn.tedu.charging.order.service.impl;

import cn.tedu.charging.common.pojo.JsonResult;
import cn.tedu.charging.common.pojo.consts.AmqpComponentConst;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.message.StartCheckMessage;
import cn.tedu.charging.common.pojo.param.UpdateGunStatusParam;
import cn.tedu.charging.common.pojo.utils.CronUtil;
import cn.tedu.charging.common.pojo.utils.SnowflakeIdGenerator;
import cn.tedu.charging.common.pojo.vo.UserDetailVO;
import cn.tedu.charging.order.amqp.AmqpProducer;
import cn.tedu.charging.order.common.GunStatus;
import cn.tedu.charging.order.feign.DeviceFeignClient;
import cn.tedu.charging.order.feign.UserFeignClient;
import cn.tedu.charging.order.mqtt.MyProducer;
import cn.tedu.charging.order.pojo.param.OrderAddParam;
import cn.tedu.charging.order.service.OrderService;
import cn.tedu.charging.order.utils.XxlJobTaskUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    /**
     * 创建订单
     *
     * @param orderAddParam
     * @return
     */
    @Override
    public String createOrder(OrderAddParam orderAddParam) {
        log.debug("业务层-Service 创建订单,入参:{}");
        String orderNo = generateOrderNo();
        log.debug("业务层-Service 创建订单,orderNo:{}", orderNo);
        Integer userId = orderAddParam.getUserId();
        //1.调用用户服务获取用户信息
        log.debug("业务层-Service 创建订单,调用用户服务获取用户信息，入参：｛｝", userId);
        UserDetailVO userDetailVO = getUserDetailByUserIdByFeignClient(userId);
        log.debug("业务层-Service 调用用户服务获取用户信息,入参:{},出参:{}", userId, userDetailVO);
        //.校验用户信息 是否存在
        /*if (userDetailVO == null) {
            log.error("创建订单，用户不存在，入参：{}", userId);
            //抛出异常     异常信息
            throw new RuntimeException("用户不存在");
        }*/
        Integer gunId = orderAddParam.getGunId();
        log.debug("业务层-Service 创建订单，调用设备服务修改抢的状态为已使用，入参:{}", gunId);

        Boolean result = updateGunStatus(gunId);
        log.debug("业务层-Service 创建订单，调用设备服务修改抢的状态为已使用，入参:{},出参:{}", gunId, result);

        log.debug("业务层-Service 给设备发送开始充电的指令，入参:{}", orderNo);
        startCharging(orderNo,orderAddParam.getUserId(),gunId,orderAddParam.getPileId());
        log.debug("发送消息");
        sendDelayMessage(orderNo,orderAddParam);
        log.debug("业务层-Service 创建订单，给xxl-job发送一个任务，入参:{}",orderNo);
        //定时任务 应该是先计算订单最大最长可能充电时间是多少,25分钟 30分钟 1小时
        //所以计划任务执行一次的时间点 也是不同的,就是当前扫码下单向后延迟{最大充电时间}时间点
        //关于订单最大充电时间,我们和延迟消息做一个区别,3分钟
        XxlJobTaskUtil.createJobTask(CronUtil.delayCron(1000*60*3),"order-executor",orderNo);
        return orderNo;
    }
    @Autowired
    private AmqpProducer amqpProducer;
    private void sendDelayMessage(String orderNo, OrderAddParam orderAddParam) {
        //1.组织一个DelayCheckMessage
        DelayCheckMessage delayCheckMessage = new DelayCheckMessage();
        delayCheckMessage.setBillId(orderNo);
        delayCheckMessage.setUserId(orderAddParam.getUserId());
        delayCheckMessage.setGunId(orderAddParam.getGunId());
        delayCheckMessage.setPileId(orderAddParam.getPileId());
        //2.将这个对象转化成json
        String message = JSON.toJSONString(delayCheckMessage);
        //3.调用延迟发送 一个设备充电桩最大自检时长是45秒钟,延迟时间比45秒钟长一点就行了 1分钟
        amqpProducer.sendDelay(AmqpComponentConst.DELAY_BILL_EX,message,1000*60);
    }

    @Autowired
    private MyProducer myProducer;
    private void startCharging(String billId,Integer userId,Integer gunId,Integer pileId) {
        //调用设备服务 给设备发送开始充电的指令
        //1.整理好消息必要参数
        StartCheckMessage startCheckMessage = new StartCheckMessage();
        startCheckMessage.setBillId(billId);
        startCheckMessage.setUserId(userId);
        startCheckMessage.setGunId(gunId);
        //2.需要将这个对象转化成json
        String json = JSON.toJSONString(startCheckMessage);
        //3.准备好主题
        String topicName="charging/device/check/"+pileId;
        //4.producer调用发送
        myProducer.send(topicName,json);

    }

    @Autowired
    private DeviceFeignClient deviceFeignClient;

    private Boolean updateGunStatus(Integer gunId) {
        UpdateGunStatusParam updateGunStatusParam = new UpdateGunStatusParam();
        updateGunStatusParam.setGunId(gunId);
        updateGunStatusParam.setGunStatus(GunStatus.CHARGING);
        JsonResult<Boolean> booleanJsonResult = deviceFeignClient.updateGunStatus(updateGunStatusParam);
        if(booleanJsonResult!=null){//判断是否为空
            return  booleanJsonResult.getData(); //有数据 返回数据  更新成功
        }
        return false; //没有数据 返回false 更新失败
    }
    @Autowired
    private SnowflakeIdGenerator snowflakeIdGenerator;
    /**
     * 生成唯一的 订单号
     */
    private String generateOrderNo() {
        //生成唯一的订单号
        return snowflakeIdGenerator.nextId()+"";
    }


    @Autowired
    private UserFeignClient userFeignClient;

    private UserDetailVO getUserDetailByUserIdByFeignClient(Integer userId) {
        JsonResult<UserDetailVO> userDetailVOJsonResult =
                userFeignClient.userDetail(userId);

        if (userDetailVOJsonResult != null) {
            return userDetailVOJsonResult.getData();
        }
        return null;
    }

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public UserDetailVO getUserDetailByUserId(Integer userId) {

        //String url="http://localhost:8080/user/detail/{userId}";
        String url = "http://charging-user/user/detail/{userId}";
        /**
         * 返回类型 JsonResult<UserDetailVO> 数据是要
         * 为什么用 ParameterizedTypeReference？
         * Java 泛型在运行时会被擦除，ParameterizedTypeReference 通过匿名子类保留泛型信息，确保正确反序列化。
         */
        ParameterizedTypeReference<JsonResult<UserDetailVO>> reptypeReference
                = new ParameterizedTypeReference<>() {
        };

        /**
         * public <T> ResponseEntity<T> exchange(
         *     String url,                     // 请求URL（可含占位符）
         *     HttpMethod method,              // HTTP方法（GET/POST等）
         *     HttpEntity<?> requestEntity,    // 请求实体（含头和体）
         *     ParameterizedTypeReference<T> responseType, // 响应类型（支持泛型）
         *     Object... uriVariables          // URL占位符参数
         * ) throws RestClientException
         *
         * 通过 exchange() 方法，可以实现高度定制的 HTTP 通信
         * 调用方式 exchange （交换）调用接口               1 接口地址 url,2 调用方式 GET 3 入参 4  返回类型 reptypeReference  5 占位符  入参 userId
         */

        ResponseEntity<JsonResult<UserDetailVO>> exchange
                = restTemplate.exchange(url, HttpMethod.GET, null, reptypeReference, userId);
        JsonResult<UserDetailVO> body = exchange.getBody();

        UserDetailVO data = body.getData();

        return data;
    }
}
